package com.tjhk.lock.clh;

import java.util.concurrent.atomic.AtomicReference;

public class CLHLock {
    private static class Node{
        private volatile boolean status = false;
    }

    /**
     * 隐式链表的队尾指针
     */
    private AtomicReference<Node> tail;

    /**
     * 当前节点
     */
    private ThreadLocal<Node> currentNode;

    /**
     * 前驱节点
     */
    private ThreadLocal<Node> prevNode;

    public CLHLock() {
        // 像隐式链表添加第一个节点，哨兵节点
        this.tail = new AtomicReference<>(new Node());
        this.currentNode = ThreadLocal.withInitial(Node::new);
        this.prevNode = new ThreadLocal<>();
    }

    public void lock(){
        // 每次第一次加锁获取一个新的Node实例作为当前节点
        Node node = currentNode.get();
        node.status = true;
        // 将当前节点加入隐式链表的队尾：
        // 通过队尾指针tail获取当前节点的oldValue作为prev
        // Atomically sets to the given value and returns the old value
        // 第二次进来则读取的是上次加锁的当前节点的状态
        Node prev = tail.getAndSet(node);
        prevNode.set(prev);
        // 等待前驱节点修改status
        while (prev.status);
    }

    public void unlock(){
        // 将status设为false,解除后继节点的自旋
        Node node = currentNode.get();
        node.status = false;
        prevNode.remove();
        currentNode.remove();
    }
}
